package io.github.harmonly.controller;

import io.github.harmonly.entity.Apply;
import io.github.harmonly.entity.User;
import io.github.harmonly.entity.activity.Activity;
import io.github.harmonly.entity.activity.ActivityComment;
import io.github.harmonly.entity.activity.Participant;
import io.github.harmonly.entity.association.Association;
import io.github.harmonly.entity.association.Member;
import io.github.harmonly.service.*;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.servlet.ModelAndView;

import javax.annotation.Resource;
import javax.servlet.http.HttpSession;
import java.util.*;

@Controller
public class PageController {

    @Resource
    private AssociationService associationService;
    @Resource
    private UserService userService;
    @Resource
    private ActivityService activityService;
    @Resource
    private FinanceService financeService;
    @Resource
    private MemberService memberService;
    @Resource
    private ParticipantService participantService;
    @Resource
    private ApplyService applyService;
    @Resource
    private StarService starService;

    @RequestMapping("/login")
    public ModelAndView login(HttpSession session) {
        String url = "auth/login";
        User user = (User) session.getAttribute("user");
        if (user != null) url = "redirect:index";
        ModelAndView modelAndView = new ModelAndView(url);
        modelAndView.getModel().put("user", user);
        if (session.getAttribute("login_error") != null) {
            modelAndView.getModel().put("login_error", true);
            session.removeAttribute("login_error");
        }
        return modelAndView;
    }

    @RequestMapping("/register")
    public ModelAndView register() {
        ModelAndView modelAndView = new ModelAndView("auth/register");
        modelAndView.getModel().put("user", null);
        return modelAndView;
    }

    // index 页面显示社团的内容
    @RequestMapping(value = "/index", method = RequestMethod.GET)
    public ModelAndView getIndex(HttpSession session) {
        User user = (User) session.getAttribute("user");
        if (user == null) return new ModelAndView("redirect:login");
        ModelAndView modelAndView = new ModelAndView("associations");

        List<Association> associations = associationService.getAssociations();
        Set<String> tags = new HashSet<>();
        associations.forEach(association -> tags.add(association.getTag()));
        List<Boolean> joinList = new ArrayList<>();
        associations.forEach(association -> {
            joinList.add(memberService.isJoin(Member.builder()
                    .uid(user.getUid())
                    .aid(association.getAid())
                    .build()));
        });

        modelAndView.getModel().put("user", user);
        modelAndView.getModel().put("associations", associations);
        modelAndView.getModel().put("joinList", joinList);
        modelAndView.getModel().put("tags", tags);
        return modelAndView;
    }

    @RequestMapping(value = "/index", method = RequestMethod.POST)
    public ModelAndView postIndexByKeyword(HttpSession session, String type, String keyword) {
        User user = (User) session.getAttribute("user");
        if (user == null) return new ModelAndView("redirect:login");
        ModelAndView modelAndView = new ModelAndView("associations");

        List<Association> associations = new ArrayList<>();
        if (type.equals("name")) {
            associations = associationService.getAssociationsByName(keyword.trim());
        } else if (type.equals("tag")) {
            associations = associationService.getAssociationsByTag(keyword.trim());
        }
        Set<String> tags = new HashSet<>();
        associationService.getAssociations().forEach(association -> tags.add(association.getTag()));
        List<Boolean> joinList = new ArrayList<>();
        associations.forEach(association -> {
            joinList.add(memberService.isJoin(Member.builder()
                    .uid(user.getUid())
                    .aid(association.getAid())
                    .build()));
        });

        modelAndView.getModel().put("user", user);
        modelAndView.getModel().put("associations", associations);
        modelAndView.getModel().put("joinList", joinList);
        modelAndView.getModel().put("tags", tags);
        return modelAndView;
    }

    @RequestMapping(value = "/association", method = RequestMethod.GET)
    public ModelAndView getAssociation(HttpSession session, int aid) {
        User user = (User) session.getAttribute("user");
        if (user == null) new ModelAndView("redirect:login");

        ModelAndView modelAndView = new ModelAndView("association");
        modelAndView.getModel().put("user", user);
        Association association = associationService.getAssociation(aid);
        List<User> users = memberService.getUsers(association.getAid());

        modelAndView.getModel().put("association", association);
        modelAndView.getModel().put("master", userService.getUser(association.getUid()));
        modelAndView.getModel().put("users", users);
        modelAndView.getModel().put("activities", activityService.getActivitiesByAid(association.getAid()));
        modelAndView.getModel().put("honors", associationService.getHonorsByAid(association.getAid()));
        modelAndView.getModel().put("finances", financeService.getFinancesByAid(association.getAid()));
        return modelAndView;
    }

    @RequestMapping(value = "/users", method = RequestMethod.GET)
    public ModelAndView getUsers(HttpSession session) {
        User user = (User) session.getAttribute("user");
        if (user == null) new ModelAndView("redirect:login");
        ModelAndView modelAndView = new ModelAndView("users");
        modelAndView.getModel().put("user", user);
        modelAndView.getModel().put("users", userService.getUsers());
        return modelAndView;
    }

    @RequestMapping(value = "/users", method = RequestMethod.POST)
    public ModelAndView postUsers(HttpSession session, String keyword) {
        User user = (User) session.getAttribute("user");
        if (user == null) new ModelAndView("redirect:login");
        ModelAndView modelAndView = new ModelAndView("users");
        modelAndView.getModel().put("user", user);
        modelAndView.getModel().put("users", userService.getUsersByKeyWord(keyword.trim()));
        return modelAndView;
    }

    @RequestMapping(value = "/activities", method = RequestMethod.GET)
    public ModelAndView getActivities(HttpSession session) {
        User user = (User) session.getAttribute("user");
        if (user == null) return new ModelAndView("redirect:login");

        List<Activity> activities = activityService.getActivities();
        List<Boolean> joinList = new ArrayList<>();
        activities.forEach(activity -> {
            joinList.add(participantService.isJoin(
                    Participant.builder()
                            .uid(user.getUid())
                            .cid(activity.getCid())
                            .build()
            ));
        });
        ModelAndView modelAndView = new ModelAndView("activities");
        modelAndView.getModel().put("user", user);
        modelAndView.getModel().put("activities", activities);
        modelAndView.getModel().put("joinList", joinList);
        return modelAndView;
    }

    @RequestMapping(value = "/activities", method = RequestMethod.POST)
    public ModelAndView postActivities(HttpSession session, String keyword) {
        User user = (User) session.getAttribute("user");
        if (user == null) return new ModelAndView("redirect:login");

        List<Activity> activities = activityService.getActivitiesByKeyWord(keyword.trim());
        List<Boolean> joinList = new ArrayList<>();
        activities.forEach(activity -> {
            joinList.add(participantService.isJoin(
                    Participant.builder()
                            .uid(user.getUid())
                            .cid(activity.getCid())
                            .build()
            ));
        });
        ModelAndView modelAndView = new ModelAndView("activities");
        modelAndView.getModel().put("user", user);
        modelAndView.getModel().put("activities", activities);
        modelAndView.getModel().put("joinList", joinList);
        return modelAndView;
    }

    @RequestMapping(value = "/activity", method = RequestMethod.GET)
    public ModelAndView getActivity(HttpSession session, int cid) {
        User user = (User) session.getAttribute("user");
        if (user == null) return new ModelAndView("redirect:login");

        ModelAndView modelAndView = new ModelAndView("activity");
        modelAndView.getModel().put("user", user);
        Activity activity = activityService.getActivity(cid);
        Association association = associationService.getAssociation(activity.getAid());
        User master = userService.getUser(association.getUid());

        List<ActivityComment> comments = activityService.getCommentsByCid(activity.getCid());
        List<User> users = new ArrayList<>();
        List<User> participants = new ArrayList<>();
        participantService.getParticipantByActivity(activity.getCid()).forEach(
                participant -> participants.add(userService.getUser(participant.getUid()
                )));
        comments.forEach(comment -> users.add(userService.getUser(comment.getUid())));
        modelAndView.getModel().put("activity", activity);
        modelAndView.getModel().put("association", association);
        modelAndView.getModel().put("master", master);
        modelAndView.getModel().put("participants", participants);
        modelAndView.getModel().put("comments", comments);
        modelAndView.getModel().put("users", users);
        modelAndView.getModel().put("starred", starService.getStarsByUser(user.getUid()).size() != 0);
        int stars = starService.getStarsByActivity(activity.getCid()).size();
        modelAndView.getModel().put("star", 1.0 * activity.getStar() / stars);
        modelAndView.getModel().put("stars", stars);
        modelAndView.getModel().put("is_join",
                participantService.isJoin(Participant.builder()
                        .uid(user.getUid())
                        .cid(activity.getCid())
                        .build()));
        return modelAndView;
    }

    @RequestMapping(value = "/finances", method = RequestMethod.GET)
    public ModelAndView getFinances(HttpSession session) {
        User user = (User) session.getAttribute("user");
        if (user == null) return new ModelAndView("redirect:login");
        ModelAndView modelAndView = new ModelAndView("finances");
        modelAndView.getModel().put("user", user);
        modelAndView.getModel().put("finances", financeService.getFinances());
        return modelAndView;
    }

    @RequestMapping(value = "/finances", method = RequestMethod.POST)
    public ModelAndView postFinances(HttpSession session, int aid) {
        User user = (User) session.getAttribute("user");
        if (user == null) return new ModelAndView("redirect:login");
        ModelAndView modelAndView = new ModelAndView("finances");
        modelAndView.getModel().put("user", user);
        modelAndView.getModel().put("finances", financeService.getFinancesByAid(aid));
        Association association = associationService.getAssociation(aid);
        if (association != null) modelAndView.getModel().put("association_name", association.getName());
        return modelAndView;
    }

    @RequestMapping(value = "/my_associations", method = RequestMethod.GET)
    public ModelAndView getMyAssociations(HttpSession session) {
        User user = (User) session.getAttribute("user");
        if (user == null) return new ModelAndView("redirect:login");

        ModelAndView modelAndView = new ModelAndView("my_associations");
        modelAndView.getModel().put("user", user);
        modelAndView.getModel().put("associations", memberService.getAssociations(user.getUid()));
        return modelAndView;
    }

    @RequestMapping(value = "/applies", method = RequestMethod.GET)
    public ModelAndView getApplies(HttpSession session) {
        User user = (User) session.getAttribute("user");
        if (user == null) return new ModelAndView("redirect:login");
        ModelAndView modelAndView = new ModelAndView("applies");
        List<Apply> applies = new ArrayList<>();
        if (user.getRole().equals("admin")) {
            applyService.getApplies().forEach(apply -> {
                if (userService.getUser(apply.getReceiver()) == null && apply.getState().equals("pending"))
                    applies.add(apply);
            });
        } else if (user.getRole().equals("master")) {
            applyService.getAppliesByReceiver(user.getUid()).forEach(apply -> {
                if (apply.getState().equals("pending")) applies.add(apply);
            });
        }
        modelAndView.getModel().put("user", user);
        modelAndView.getModel().put("applies", applies);
        return modelAndView;
    }
}
